schedule/SMT_EXPELLER: openeuler SMT_EXPELLER mermaid

This commit is contained in:
Cheng Jian
2022-12-27 09:32:39 +08:00
parent a048e5e794
commit 35c0170837
4 changed files with 214 additions and 0 deletions
@@ -0,0 +1,69 @@
---
title: 混部隔离技术之 SMT 驱逐
date: 2021-06-26 09:40
author: gatieme
tags:
- linux
- tools
categories:
- 技术积累
thumbnail:
blogexcerpt: 虚拟化 & KVM 子系统
---
<br>
本作品采用<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可, 转载请注明出处, 谢谢合作
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a>
因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 鄙人在此谢谢啦
**转载请务必注明出处, 谢谢, 不胜感激**
<br>
| 日期 | 作者 | GitHub| CSDN | BLOG |
| ------- |:-------:|:-------:|:-------:|:-------:|
| 2021-02-15 | [成坚-gatieme](https://kernel.blog.csdn.net) | [`AderXCoding/system/tools/fzf`](https://github.com/gatieme/AderXCoding/tree/master/system/tools/fzf) | [使用模糊搜索神器 FZF 来提升办公体验](https://blog.csdn.net/gatieme/article/details/113828826) | [Using FZF to Improve Productivit](https://oskernellab.com/2021/02/15/2021/0215-0001-Using_FZF_to_Improve_Productivity)|
<br>
**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 重要功能和时间点 -*-*-*-*-*-*-*-*-*-*-*-*-*-*-***
下文将按此目录分析 Linux 内核中 SMT_EXPELLER 的重要功能和引入版本:
**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 正文 -*-*-*-*-*-*-*-*-*-*-*-*-*-*-***
# 1 SMT_EXPELLER
-------
# 2 openEuler CONFIG_QOS_SCHED_SMT_EXPELLER
-------
[openEuler QOS_SCHED_SMT_EXPELLER 主体流程框架](./qos_smt_expeller.mmd)
<br>
* 本作品/博文 ( [AderStep-紫夜阑珊-青伶巷草 Copyright ©2013-2017](http://blog.csdn.net/gatieme) ), 由 [成坚(gatieme)](http://blog.csdn.net/gatieme) 创作.
* 采用<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) (包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的.
* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问, 请与我联系.
* **转载请务必注明出处, 谢谢, 不胜感激**
<br>
@@ -0,0 +1,51 @@
flowchart TB
pick_next_task_fair --PICK 前检查是否进行/保持驱逐--> QoSSmtExpelled
pick_next_task_fair --PICK 到 TASK 后尝试 SMT 驱离--> QosSmtQxpelTask -...-> scheduler_ipi
pick_next_task_fair --当前 CPU 即将 IDLE 尝试更新驱离状态--> QosSmtQxpelIdle -...-> scheduler_ipi
%% 如果 THIS CPU 的 Siblings CPU 是 QOS_LEVEL_ONLINE 的状态, 且 THIS CPU 没有在线任务在等待队列, 则强制 THIS CPU 进入 FORCE IDLE.
%% 保持驱离状态.
subgraph QoSSmtExpelled ["保持 SMT 驱逐状态"]
direction TB
qos_smt_expelled --> QoSSmtCheckSiblingsStatus --> QOS_LEVEL_OFFLINE1["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"]
qos_smt_expelled --> sched_idle_cpu --> QOS_LEVEL_OFFLINE1["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"]
QOS_LEVEL_OFFLINE1 --> pick_NULL;
subgraph QoSSmtCheckSiblingsStatus["qos_smt_check_siblings_status(this_cpu)"]
direction TB
check_siblings_status("除 this_cpu 之外所有 siblings CPU 均是 QOS_LEVEL_ONLINE")
end
end
%% 如果 THIS CPU PICK 到了一个 TASK p, 则依据其是 ONLINE/OFFLINE 任务, 决定是否进行驱离.
%% 驱离通过给其 Siblings CPU 发送 RESCHED IPI 发送重调度来完成.
subgraph QosSmtQxpelTask [触发 SMT 驱逐]
direction TB
qos_smt_expel_task("qos_smt_expel(this_cpu, p)");
end
%% 如果 THIS CPU 没有 PICK 到任务, 则依据其是 ONLINE/OFFLINE 任务, 决定是否进行驱离.
%% 驱离通过给其 Siblings CPU 发送 RESCHED IPI 发送重调度来完成.
subgraph QosSmtQxpelIdle [触发 SMT 驱逐]
direction TB
qos_smt_expel_idle("qos_smt_expel(this_cpu, NULL)");
end
subgraph SchedulerIPI [执行 SMT 驱逐]
direction TB
%% Siblings CPU 接收到 RESCHED IPI 后, 设置 RESCHED 标记, 则下次触发 pick_next_task_fair 的时候, 讲进行驱逐.
scheduler_ipi --> qos_smt_check_need_resched --> QoSSmtCheckNeedResched --> set_tsk_need_resched["set_tsk_need_resched(current)"]
subgraph QoSSmtCheckNeedResched [执行驱逐]
direction TB
_qos_smt_check_need_resched --> for_each_siblings_cpu2;
%% 如果 THIS CPU 的 Siblings CPU 是 QOS_LEVEL_ONLINE, 但是 THIS CPU 正在执行的是 OFFLINE 任务, 需要进行驱逐, THIS CPU 触发 RESCHED, pick_next_task_fair 会选择 NULL.
for_each_siblings_cpu2 --Siblings CPU 上执行在线任务--> this_cpu_must_be_expeller("per_cpu(qos_smt_status, cpu) == QOS_LEVEL_ONLINE && task_group(current)->qos_level < QOS_LEVEL_ONLINE");
%% 如果 THIS CPU 的 Siblings CPU 是 QOS_LEVEL_OFFLINE, 且是 IDLE 状态, 而 THIS CPU 上只有离线任务, 没有在线任务, 同样需要触发 RESCHED, pick_next_task_fair 尝试选择一个 ONLINE 任务出来.
for_each_siblings_cpu2 --Siblings CPU 上执行离线任务--> this_cpu_can_run_IDLE("per_cpu(qos_smt_status, cpu) == QOS_LEVEL_OFFLINE && rq->curr == rq->idle && sched_idle_cpu(this_cpu)");
end
end
@@ -0,0 +1,66 @@
flowchart TB
pick_next_task_fair --PICK 前检查是否进行/保持驱逐--> QoSSmtExpelled
pick_next_task_fair --PICK 到 TASK 后尝试 SMT 驱离--> QosSmtQxpelTask %%-...-> scheduler_ipi;
pick_next_task_fair --当前 CPU 即将 IDLE 尝试更新驱离状态--> QosSmtQxpelIdle %%-...-> scheduler_ipi;
%% 如果 THIS CPU 的 Siblings CPU 是 QOS_LEVEL_ONLINE 的状态, 且 THIS CPU 没有在线任务在等待队列, 则强制 THIS CPU 进入 FORCE IDLE.
%% 保持驱离状态.
subgraph QoSSmtExpelled ["保持 SMT 驱逐状态"]
direction TB
qos_smt_expelled --> QoSSmtCheckSiblingsStatus --> QOS_LEVEL_OFFLINE1["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"]
qos_smt_expelled --> sched_idle_cpu --> QOS_LEVEL_OFFLINE1["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"]
QOS_LEVEL_OFFLINE1 --> pick_NULL;
subgraph QoSSmtCheckSiblingsStatus["qos_smt_check_siblings_status(this_cpu)"]
direction TB
check_siblings_status("除 this_cpu 之外所有 siblings CPU 均是 QOS_LEVEL_ONLINE")
end
end
%% 如果 THIS CPU PICK 到了一个 TASK p, 则依据其是 ONLINE/OFFLINE 任务, 决定是否进行驱离.
%% 驱离通过给其 Siblings CPU 发送 RESCHED IPI 发送重调度来完成.
subgraph QosSmtQxpelTask [触发 SMT 驱逐]
direction TB
qos_smt_expel_task("qos_smt_expel(this_cpu, p)") --> QoSSmtUpdateStatus;
subgraph QoSSmtUpdateStatus[检查是否需要进行 SMT 驱逐]
direction TB
qos_smt_update_status["qos_smt_update_status(p)"] --> is_task_online{{"task_group(p)->qos_level >= QOS_LEVEL_ONLINE"}};
is_task_online --yes--> QOS_LEVEL_ONLINE["__this_cpu_write(qos_smt_status, QOS_LEVEL_ONLINE)"] --> QoSSmtSendIPI;
is_task_online --no--> QOS_LEVEL_OFFLINE2["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"];
end
subgraph QoSSmtSendIPI[通知所有 siblings CPU 进行驱逐]
direction TB
qos_smt_send_ipi["qos_smt_send_ipi(this_cpu)"] --> for_each_siblings_cpu1("for_each_cpu(cpu, cpu_smt_mask(this_cpu))") --"per_cpu(qos_smt_status, cpu) != QOS_LEVEL_ONLINE && rq->cfs.h_nr_running != 0"--> smp_send_reschedule_task("smp_send_reschedule(cpu)") %%-...-> scheduler_ipi;
end
end
%% 如果 THIS CPU 没有 PICK 到任务, 则依据其是 ONLINE/OFFLINE 任务, 决定是否进行驱离.
%% 驱离通过给其 Siblings CPU 发送 RESCHED IPI 发送重调度来完成.
subgraph QosSmtQxpelIdle [触发 SMT 驱逐]
direction TB
qos_smt_expel_idle("qos_smt_expel(this_cpu, NULL)") --> QOS_LEVEL_OFFLINE3["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"] --> smp_send_reschedule_idle("smp_send_reschedule(cpu)") %%-...-> scheduler_ipi;
end
%% flowchart TB
%% smp_send_reschedule_idle -...-> scheduler_ipi
%% smp_send_reschedule_task -...-> scheduler_ipi
subgraph SchedulerIPI [执行 SMT 驱逐]
direction TB
%% Siblings CPU 接收到 RESCHED IPI 后, 设置 RESCHED 标记, 则下次触发 pick_next_task_fair 的时候, 讲进行驱逐.
scheduler_ipi --> qos_smt_check_need_resched --> QoSSmtCheckNeedResched --> set_tsk_need_resched["set_tsk_need_resched(current)"]
subgraph QoSSmtCheckNeedResched [执行驱逐]
direction TB
_qos_smt_check_need_resched --> for_each_siblings_cpu2;
%% 如果 THIS CPU 的 Siblings CPU 是 QOS_LEVEL_ONLINE, 但是 THIS CPU 正在执行的是 OFFLINE 任务, 需要进行驱逐, THIS CPU 触发 RESCHED, pick_next_task_fair 会选择 NULL.
for_each_siblings_cpu2 --Siblings CPU 上执行在线任务--> this_cpu_must_be_expeller("per_cpu(qos_smt_status, cpu) == QOS_LEVEL_ONLINE && task_group(current)->qos_level < QOS_LEVEL_ONLINE");
%% 如果 THIS CPU 的 Siblings CPU 是 QOS_LEVEL_OFFLINE, 且是 IDLE 状态, 而 THIS CPU 上只有离线任务, 没有在线任务, 同样需要触发 RESCHED, pick_next_task_fair 尝试选择一个 ONLINE 任务出来.
for_each_siblings_cpu2 --Siblings CPU 上执行离线任务--> this_cpu_can_run_IDLE("per_cpu(qos_smt_status, cpu) == QOS_LEVEL_OFFLINE && rq->curr == rq->idle && sched_idle_cpu(this_cpu)");
end
end
@@ -0,0 +1,28 @@
flowchart TB
pick_next_task_fair --PICK 到 TASK 后尝试 SMT 驱离--> QosSmtQxpelTask
pick_next_task_fair --当前 CPU 即将 IDLE 尝试更新驱离状态--> QosSmtQxpelIdle
%% 如果 THIS CPU PICK 到了一个 TASK p, 则依据其是 ONLINE/OFFLINE 任务, 决定是否进行驱离.
%% 驱离通过给其 Siblings CPU 发送 RESCHED IPI 发送重调度来完成.
subgraph QosSmtQxpelTask [触发 SMT 驱逐]
direction TB
qos_smt_expel_task("qos_smt_expel(this_cpu, p)") --> QoSSmtUpdateStatus;
subgraph QoSSmtUpdateStatus[检查是否需要进行 SMT 驱逐]
direction TB
qos_smt_update_status["qos_smt_update_status(p)"] --> is_task_online{{"task_group(p)->qos_level >= QOS_LEVEL_ONLINE"}};
is_task_online --yes--> QOS_LEVEL_ONLINE["__this_cpu_write(qos_smt_status, QOS_LEVEL_ONLINE)"] --> QoSSmtSendIPI;
is_task_online --no--> QOS_LEVEL_OFFLINE2["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"];
end
subgraph QoSSmtSendIPI[通知所有 siblings CPU 进行驱逐]
direction TB
qos_smt_send_ipi["qos_smt_send_ipi(this_cpu)"] --> for_each_siblings_cpu1("for_each_cpu(cpu, cpu_smt_mask(this_cpu))") --"per_cpu(qos_smt_status, cpu) != QOS_LEVEL_ONLINE && rq->cfs.h_nr_running != 0"--> smp_send_reschedule_task("smp_send_reschedule(cpu)");
end
end
%% 如果 THIS CPU 没有 PICK 到任务, 则依据其是 ONLINE/OFFLINE 任务, 决定是否进行驱离.
%% 驱离通过给其 Siblings CPU 发送 RESCHED IPI 发送重调度来完成.
subgraph QosSmtQxpelIdle [触发 SMT 驱逐]
direction TB
qos_smt_expel_idle("qos_smt_expel(this_cpu, NULL)") --> QOS_LEVEL_OFFLINE3["__this_cpu_write(qos_smt_status, QOS_LEVEL_OFFLINE)"] --> smp_send_reschedule_idle("smp_send_reschedule(cpu)");
end