更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_mp.c
浏览该文件的文档.
1/*!
2 * @file los_mp.c
3 * @brief
4 * @link
5 * @verbatim
6 多CPU核的操作系统3种处理模式(SMP+AMP+BMP) 鸿蒙实现的是 SMP 的方式
7 非对称多处理(Asymmetric multiprocessing,AMP)每个CPU内核
8 运行一个独立的操作系统或同一操作系统的独立实例(instantiation)。
9
10 对称多处理(Symmetric multiprocessing,SMP)一个操作系统的实例
11 可以同时管理所有CPU内核,且应用并不绑定某一个内核。
12
13 混合多处理(Bound multiprocessing,BMP)一个操作系统的实例可以
14 同时管理所有CPU内核,但每个应用被锁定于某个指定的核心。
15
16 多核多线程处理器的中断
17 由 PIC(Programmable Interrupt Controller)统一控制。PIC 允许一个
18 硬件线程中断其他的硬件线程,这种方式被称为核间中断(Inter-Processor Interrupts,IPI)
19
20 SGI:软件触发中断(Software Generated Interrupt)。在arm处理器中,
21 SGI共有16个,硬件中断号分别为ID0~ID15。它通常用于多核间通讯。
22 * @endverbatim
23 * @version
24 * @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
25 * @date 2021-11-18
26 *
27 * @history
28 *
29 */
30/*
31 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
32 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without modification,
35 * are permitted provided that the following conditions are met:
36 *
37 * 1. Redistributions of source code must retain the above copyright notice, this list of
38 * conditions and the following disclaimer.
39 *
40 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
41 * of conditions and the following disclaimer in the documentation and/or other materials
42 * provided with the distribution.
43 *
44 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
45 * to endorse or promote products derived from this software without specific prior written
46 * permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
50 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
52 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
55 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
56 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
57 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
58 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60
61#include "los_mp.h"
62#include "los_init.h"
63#include "los_percpu_pri.h"
64#include "los_sched_pri.h"
65#include "los_swtmr.h"
66#include "los_task_pri.h"
67
68
69#ifdef LOSCFG_KERNEL_SMP
70//给参数CPU发送调度信号
71#ifdef LOSCFG_KERNEL_SMP_CALL
72LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_mpCallSpin);
73#define MP_CALL_LOCK(state) LOS_SpinLockSave(&g_mpCallSpin, &(state))
74#define MP_CALL_UNLOCK(state) LOS_SpinUnlockRestore(&g_mpCallSpin, (state))
75#endif
76VOID LOS_MpSchedule(UINT32 target)//target每位对应CPU core
77{
78 UINT32 cpuid = ArchCurrCpuid();
79 target &= ~(1U << cpuid);//获取除了自身之外的其他CPU
80 HalIrqSendIpi(target, LOS_MP_IPI_SCHEDULE);//向目标CPU发送调度信号,核间中断(Inter-Processor Interrupts),IPI
81}
82///硬中断唤醒处理函数
84{
85 /* generic wakeup ipi, do nothing */
86}
87///硬中断调度处理函数
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}
96///硬中断暂停处理函数
98{
99 (VOID)LOS_IntLock();
100 OsPercpuGet()->excFlag = CPU_HALT;//让当前Cpu停止工作
101
102 while (1) {}//陷入空循环,也就是空闲状态
103}
104///MP定时器处理函数, 递归检查所有可用任务
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}
131
132#ifdef LOSCFG_KERNEL_SMP_CALL
133/*!
134 * @brief OsMpFuncCall
135 * 向指定CPU的funcLink上注册回调函数, 该怎么理解这个函数呢 ? 具体有什么用呢 ?
136 * \n 可由CPU a核向b核发起一个请求,让b核去执行某个函数, 这是否是分布式调度的底层实现基础 ?
137 * @param args
138 * @param func
139 * @param target
140 * @return
141 *
142 * @see
143 */
144VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args)
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}
174
175/*!
176 * @brief OsMpFuncCallHandler
177 * 回调向当前CPU注册过的函数
178 * @return
179 *
180 * @see
181 */
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}
203/// CPU层级的回调模块初始化
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}
212#endif /* LOSCFG_KERNEL_SMP_CALL */
213//MP(multiprocessing) 多核处理器初始化
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}
226
227LOS_MODULE_INIT(OsMpInit, LOS_INIT_LEVEL_KMOD_TASK);//多处理器模块初始化
228
229#endif
230
VOID HalIrqSendIpi(UINT32 target, UINT32 ipi)
Definition: gic_v2.c:58
STATIC INLINE UINT32 LOS_IntLock(VOID)
Disable all interrupts. | 关闭当前处理器所有中断响应
Definition: los_hwi.h:286
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
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 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
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
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
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
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 UINT32 ArchCurrCpuid(VOID)
Definition: los_hw_cpu.h:168
VOID OsMpCollectTasks(VOID)
MP定时器处理函数, 递归检查所有可用任务
Definition: los_mp.c:105
VOID OsMpWakeHandler(VOID)
硬中断唤醒处理函数
Definition: los_mp.c:83
UINT32 OsMpInit(VOID)
Definition: los_mp.c:214
VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args)
OsMpFuncCall 向指定CPU的funcLink上注册回调函数, 该怎么理解这个函数呢 ? 具体有什么用呢 ? 可由CPU a核向b核发起一个请求,让b核去执行某个函数,...
Definition: los_mp.c:144
VOID LOS_MpSchedule(UINT32 target)
Definition: los_mp.c:76
VOID OsMpFuncCallInit(VOID)
CPU层级的回调模块初始化
Definition: los_mp.c:204
VOID OsMpFuncCallHandler(VOID)
OsMpFuncCallHandler 回调向当前CPU注册过的函数
Definition: los_mp.c:182
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_mpCallSpin)
VOID OsMpScheduleHandler(VOID)
硬中断调度处理函数
Definition: los_mp.c:88
VOID OsMpHaltHandler(VOID)
硬中断暂停处理函数
Definition: los_mp.c:97
LOS_MODULE_INIT(OsMpInit, LOS_INIT_LEVEL_KMOD_TASK)
VOID(* SMP_FUNC_CALL)(VOID *args)
Definition: los_mp.h:58
@ LOS_MP_IPI_SCHEDULE
!< 唤醒CPU
Definition: los_mp.h:51
@ 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
@ CPU_HALT
cpu in the halt | CPU处于暂停状态
STATIC INLINE Percpu * OsPercpuGet(VOID)
STATIC INLINE BOOL OsTaskIsRunning(const LosTaskCB *taskCB)
STATIC INLINE VOID OsSchedRunqueuePendingSet(VOID)
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
任务是否在使用
Definition: los_task_pri.h:255
unsigned short UINT16
Definition: los_typedef.h:56
unsigned int UINT32
Definition: los_typedef.h:57
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
UINT32 excFlag
UINT32 signal