forked from linuxkerneltravel/lmp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'linuxkerneltravel:develop' into develop
- Loading branch information
Showing
27 changed files
with
1,312 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
178 changes: 178 additions & 0 deletions
178
eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/schedule_image.bpf.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// Copyright 2023 The LMP Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
// author: [email protected] | ||
// | ||
// eBPF kernel-mode code that collects process schedule information | ||
|
||
#include <vmlinux.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_core_read.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include "proc_image.h" | ||
|
||
char LICENSE[] SEC("license") = "Dual BSD/GPL"; | ||
|
||
const volatile pid_t target_pid = -1; | ||
const volatile int target_cpu_id = -1; | ||
const volatile pid_t ignore_tgid = -1; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__uint(max_entries, 10240); | ||
__type(key, struct proc_id); | ||
__type(value,struct schedule_event); | ||
} proc_schedule SEC(".maps"); | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__uint(max_entries, 10240); | ||
__type(key, struct proc_id); | ||
__type(value,bool); | ||
} enable_add SEC(".maps"); | ||
|
||
SEC("tp_btf/sched_wakeup") | ||
int BPF_PROG(sched_wakeup, struct task_struct *p) | ||
{ | ||
pid_t pid = BPF_CORE_READ(p,pid); | ||
int tgid = BPF_CORE_READ(p,tgid); | ||
int cpu = bpf_get_smp_processor_id(); | ||
|
||
if(tgid!=ignore_tgid && (target_pid==-1 || (target_pid!=0 && pid==target_pid) || | ||
(target_pid==0 && pid==target_pid && cpu==target_cpu_id))){ | ||
struct schedule_event *schedule_event; | ||
struct proc_id pd = {}; | ||
u64 current_time = bpf_ktime_get_ns(); | ||
|
||
pd.pid = pid; | ||
if(pid == 0) pd.cpu_id = cpu; | ||
schedule_event = bpf_map_lookup_elem(&proc_schedule,&pd); | ||
if(!schedule_event){ | ||
struct schedule_event schedule_event = {}; | ||
bool e_add = false; | ||
|
||
schedule_event.pid = pid; | ||
// 提前将 count 值赋值为 1,避免输出时进程还没有被调度,导致除数出现 0 的情况 | ||
schedule_event.count = 1; | ||
schedule_event.enter_time = current_time; | ||
|
||
bpf_map_update_elem(&enable_add,&pd,&e_add,BPF_ANY); | ||
bpf_map_update_elem(&proc_schedule,&pd,&schedule_event,BPF_ANY); | ||
}else{ | ||
schedule_event->enter_time = current_time; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
SEC("tp_btf/sched_wakeup_new") | ||
int BPF_PROG(sched_wakeup_new, struct task_struct *p) | ||
{ | ||
pid_t pid = BPF_CORE_READ(p,pid); | ||
int tgid = BPF_CORE_READ(p,tgid); | ||
int cpu = bpf_get_smp_processor_id(); | ||
|
||
if(tgid!=ignore_tgid && (target_pid==-1 || (target_pid!=0 && pid==target_pid) || | ||
(target_pid==0 && pid==target_pid && cpu==target_cpu_id))){ | ||
struct schedule_event *schedule_event; | ||
struct proc_id pd = {}; | ||
u64 current_time = bpf_ktime_get_ns(); | ||
|
||
pd.pid = pid; | ||
if(pid == 0) pd.cpu_id = cpu; | ||
schedule_event = bpf_map_lookup_elem(&proc_schedule,&pd); | ||
if(!schedule_event){ | ||
struct schedule_event schedule_event = {}; | ||
bool e_add = false; | ||
|
||
schedule_event.pid = pid; | ||
schedule_event.count = 1; | ||
schedule_event.enter_time = current_time; | ||
|
||
bpf_map_update_elem(&enable_add,&pd,&e_add,BPF_ANY); | ||
bpf_map_update_elem(&proc_schedule,&pd,&schedule_event,BPF_ANY); | ||
}else{ | ||
schedule_event->enter_time = current_time; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
SEC("tp_btf/sched_switch") | ||
int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_struct *next) | ||
{ | ||
pid_t prev_pid = BPF_CORE_READ(prev,pid); | ||
int prev_tgid = BPF_CORE_READ(prev,tgid); | ||
int prev_cpu = bpf_get_smp_processor_id(); | ||
unsigned int prev_state = BPF_CORE_READ(prev,__state); | ||
pid_t next_pid = BPF_CORE_READ(next,pid); | ||
int next_tgid = BPF_CORE_READ(next,tgid); | ||
int next_cpu = prev_cpu; | ||
u64 current_time = bpf_ktime_get_ns(); | ||
|
||
if(prev_tgid!=ignore_tgid && prev_state==TASK_RUNNING && (target_pid==-1 || (target_pid!=0 && prev_pid==target_pid) || | ||
(target_pid==0 && prev_pid==target_pid && prev_cpu==target_cpu_id))){ | ||
struct schedule_event *schedule_event; | ||
struct proc_id pd = {}; | ||
|
||
pd.pid = prev_pid; | ||
if(prev_pid == 0) pd.cpu_id = prev_cpu; | ||
schedule_event = bpf_map_lookup_elem(&proc_schedule,&pd); | ||
if(!schedule_event){ | ||
struct schedule_event schedule_event = {}; | ||
bool e_add = false; | ||
|
||
schedule_event.pid = prev_pid; | ||
schedule_event.count = 1; | ||
schedule_event.enter_time = current_time; | ||
|
||
bpf_map_update_elem(&enable_add,&pd,&e_add,BPF_ANY); | ||
bpf_map_update_elem(&proc_schedule,&pd,&schedule_event,BPF_ANY); | ||
}else{ | ||
schedule_event->enter_time = current_time; | ||
} | ||
} | ||
|
||
if(next_tgid!=ignore_tgid && (target_pid==-1 || (target_pid!=0 && next_pid==target_pid) || | ||
(target_pid==0 && next_pid==target_pid && next_cpu==target_cpu_id))){ | ||
struct schedule_event *schedule_event; | ||
bool * e_add; | ||
struct proc_id pd = {}; | ||
u64 this_delay; | ||
|
||
pd.pid = next_pid; | ||
if(next_pid == 0) pd.cpu_id = next_cpu; | ||
schedule_event = bpf_map_lookup_elem(&proc_schedule,&pd); | ||
if(!schedule_event) | ||
return 0; | ||
|
||
e_add = bpf_map_lookup_elem(&enable_add,&pd); | ||
if(!e_add) return 0; | ||
// 因为 count 值初值赋值为了 1,避免多加一次 | ||
if(*e_add) schedule_event->count++; | ||
else *e_add = true; | ||
this_delay = current_time-schedule_event->enter_time; | ||
|
||
schedule_event->prio = BPF_CORE_READ(next,prio); | ||
schedule_event->sum_delay += this_delay; | ||
if(this_delay > schedule_event->max_delay) | ||
schedule_event->max_delay = this_delay; | ||
if(schedule_event->min_delay==0 || this_delay<schedule_event->min_delay) | ||
schedule_event->min_delay = this_delay; | ||
} | ||
|
||
return 0; | ||
} |
31 changes: 31 additions & 0 deletions
31
eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/schedule_develop.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# schedule功能类开发文档 | ||
|
||
**参考资料:** | ||
|
||
- [Linux 的调度延迟 - 原理与观测 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/462728452) | ||
- [linux 内核抢占那些事 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/166032722) | ||
|
||
**调度延迟的计算得分两种情况:** | ||
|
||
1. 任务因等待 event 进入休眠态([Voluntary Switch](https://zhuanlan.zhihu.com/p/402423877)),那么就是从被唤醒("wakeup/wakeup_new" 的时间点),到获得 CPU (任务切换时的 *"next_pid"*)的间隔。 | ||
2. 任务因 [Involuntary Switch](https://zhuanlan.zhihu.com/p/402423877) 让出 CPU(任务切换时作为 *"prev_pid"*),到再次获得 CPU (之后的某次任务切换时作为*"next_pid"*)所经历的时间。在这期间,任务始终在 runqueue 上,始终是 runnable 的状态,所以有 "prev_state" 是否为 *TASK_RUNNING* 的判断。 | ||
|
||
**内核中提供了三个接口来唤醒进程:** | ||
|
||
- wake_up_new_task:用来唤醒新进程,fork出来的进程/线程; | ||
- wake_up_process:唤醒处于TASK_NORMAL状态的进程; | ||
- wake_up_state:唤醒指定状态的进程; | ||
|
||
后两个接口最终都会调用try_to_wake_up接口: | ||
|
||
``` | ||
try_to_wake_up-->ttwu_queue-->ttwu_do_active-->ttwu_do_wakeup | ||
``` | ||
|
||
**相关挂载点:** | ||
|
||
``` | ||
ttwu_do_wakeup() --> trace_sched_wakeup | ||
wake_up_new_task() --> trace_sched_wakeup_new | ||
__schedule() --> trace_sched_switch | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.