ucli perf software irq

This commit is contained in:
zy
2023-12-14 02:22:17 -05:00
parent 5d9fd19ddb
commit a7e4c1e4fa
12 changed files with 207 additions and 84 deletions

View File

@@ -2,6 +2,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/interrupt.h>
// #include <linux/sched/task.h>
// #include <linux/sched/mm.h>
@@ -119,11 +120,14 @@ static void diag_tsk(struct task_struct *p, variable_monitor_task *tsk_info) {
unsigned int nr_bt;
// printk(KERN_INFO "diag_tsk\n");
diag_task_brief(p, &tsk_info->task); // task brief
// diag_task_user_stack(p, &tsk_info->user_stack); // user stack
nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack
dump_proc_chains_argv(1, p, &mm_tree_struct,
&tsk_info->proc_chains); // proc chains
diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack
if (tsk_info->task.sys_task == 1) { // system task
nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack
} else { // other task
nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack
dump_proc_chains_argv(1, p, &mm_tree_struct,
&tsk_info->proc_chains); // proc chains
diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack
}
}
static void push_tskinfo_2_buffer_orig(variable_monitor_task *tsk_info,
@@ -203,31 +207,25 @@ static void clear_all_watch(void) {
memset(kernel_wtimer_list, 0, sizeof(kernel_wtimer_list));
}
void diag_task_info(kernel_watch_timer *k_watch_timer) {
if (k_watch_timer->threshold_over_count <= 0) // if no threshold reached
return;
static void diag_vm_record(kernel_watch_timer *k_watch_timer,
unsigned char is_print) {
static variable_monitor_record vm_record;
// printk(KERN_INFO "diag_task_info_work\n");
struct task_struct *g, *p; // g: task group; p: task
unsigned long flags;
unsigned long event_id = get_cycles();
static variable_monitor_task tsk_info = {0};
static variable_monitor_record vm_record = {0};
kernel_watch_arg *kwarg;
int i;
unsigned long flags;
unsigned long event_id = get_cycles();
vm_record.id = event_id;
vm_record.et_type = VARIABLE_MONITOR_RECORD_TYPE;
vm_record.tv = k_watch_timer->tv;
vm_record.threshold_over_count = k_watch_timer->threshold_over_count;
int i;
for (i = 0; i < vm_record.threshold_over_count; i++) {
kwarg = &k_watch_timer->k_watch_args[k_watch_timer->threshold_buffer[i]];
k_w_arg2threshold(kwarg, &vm_record.threshold_record[i]);
}
rcu_read_lock();
diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags);
@@ -236,21 +234,92 @@ void diag_task_info(kernel_watch_timer *k_watch_timer) {
diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, &vm_record,
sizeof(variable_monitor_record));
diag_variant_buffer_seal(&load_monitor_variant_buffer);
// diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags);
// for task info
diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags);
rcu_read_unlock();
if (is_print) {
printk(KERN_INFO "-----------variable monitor----------\n");
printk(KERN_INFO "threshold exceeded, Timestamp %lld, Delay %lld:\n",
vm_record.tv, ktime_get_real() - vm_record.tv);
for (i = 0; i < vm_record.threshold_over_count; i++) {
printk(
KERN_INFO
"\t: pid: %d, name: %s, ptr: %p, threshold:%lld, true_value:%lld\n",
vm_record.threshold_record[i].task_id,
vm_record.threshold_record[i]
.name, // Assuming name is a null-terminated string
vm_record.threshold_record[i].ptr,
vm_record.threshold_record[i].threshold,
vm_record.threshold_record[i].true_value);
}
printk(KERN_INFO "-------------------------------------\n");
}
}
void diag_task_by_tgid(pid_t tgid){
struct task_struct *tsk;
int ret;
unsigned long flags;
static variable_monitor_task tsk_info;
tsk = NULL;
rcu_read_lock();
tsk = NULL;
if (orig_find_task_by_vpid)
tsk = orig_find_task_by_vpid(tgid);
if (!tsk) {
ret = -EINVAL;
rcu_read_unlock();
return ;
}
diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags);
struct task_struct *thread = tsk;
unsigned long event_id = get_cycles();
while_each_thread(tsk, thread) {
tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE;
tsk_info.id = event_id;
tsk_info.tv = ktime_get_real();
diag_tsk(tsk, &tsk_info);
push_tskinfo_22_buffer(&tsk_info, &flags); // push to buffer
}
diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags);
rcu_read_unlock();
}
void diag_task_all(void){
pr_info("diag_task_all, tv %lld\n", ktime_get_real());
static variable_monitor_task tsk_info;
unsigned long event_id = get_cycles();
struct task_struct *g, *p; // g: task group; p: task
unsigned long flags;
rcu_read_lock();
diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags);
do_each_thread(g, p) {
if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) ||
((READ_ONCE(p->__state) & TASK_IDLE) != 0)) {
get_task_struct(p); // count +1
// get_task_struct(p); // count +1
tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE;
tsk_info.id = event_id;
tsk_info.tv = vm_record.tv;
tsk_info.tv = ktime_get_real();
diag_tsk(p, &tsk_info);
put_task_struct(p); // count -1
// put_task_struct(p); // count -1
push_tskinfo_22_buffer(&tsk_info, &flags); // push to buffer
}
@@ -259,24 +328,14 @@ void diag_task_info(kernel_watch_timer *k_watch_timer) {
diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags);
rcu_read_unlock();
pr_info("diag_task_all, finish tv %lld\n", ktime_get_real());
}
printk(KERN_INFO "-----------variable monitor----------\n");
printk(KERN_INFO "threshold exceeded, Timestamp %lld, Delay %lld:\n",
vm_record.tv, ktime_get_real() - vm_record.tv);
for (i = 0; i < vm_record.threshold_over_count; i++) {
printk(KERN_INFO
"\t: pid: %d, name: %s, ptr: %p, threshold:%lld, true_value:%lld\n",
vm_record.threshold_record[i].task_id,
vm_record.threshold_record[i]
.name, // Assuming name is a null-terminated string
vm_record.threshold_record[i].ptr,
vm_record.threshold_record[i].threshold,
vm_record.threshold_record[i].true_value);
}
printk(KERN_INFO "-------------------------------------\n");
return;
void diag_task_info(kernel_watch_timer *k_watch_timer) {
if (k_watch_timer->threshold_over_count <= 0) // if no threshold reached
return;
diag_task_all();
diag_vm_record(k_watch_timer, 1);
}
/**
@@ -400,6 +459,10 @@ void clear_watch(pid_t pid) {
start_all_hrTimer(); // restart timer
}
// enum {
// MY_SOFTIRQ = 11, // 这个值是示例,确保它没有被其他软中断使用
// };
/**
* @brief main callback function
*
@@ -429,9 +492,13 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) {
{
k_watch_timer->threshold_over_count = j;
k_watch_timer->tv = ktime_get_real();
pr_info("threshold reached, tv %lld\n", k_watch_timer->tv);
// highpri_wq
queue_work(system_highpri_wq, &k_watch_timer->wk);
// queue_work(system_highpri_wq, &k_watch_timer->wk);
diag_task_info(k_watch_timer);
// orig_raise_softirq(MY_SOFTIRQ); // for test
// restart timer after dump_reset_sec sec
hrtimer_forward(timer, timer->base->get_time(),
ktime_set(dump_reset_sec, 0));