diff --git a/source/module/monitor_kernel.c b/source/module/monitor_kernel.c index c6350d4..fd83158 100644 --- a/source/module/monitor_kernel.c +++ b/source/module/monitor_kernel.c @@ -49,7 +49,7 @@ typedef struct { static long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { int ret = 0; - // watch_arg warg; + watch_arg warg; ioctl_dump_param dump_param; ioctl_pid wpid; @@ -58,19 +58,19 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num, ioctl_num); switch (ioctl_num) { - // case 0: - // // copy watch_arg - // if (copy_from_user(&warg, (watch_arg *)ioctl_param, sizeof(warg))) { - // return -EACCES; - // } - // printk(KERN_INFO - // "Watch_arg: task_id=%d, name=%s, ptr=%p, length_byte=%d, " - // "time_ns=%ld, threshold=%lld\n", - // warg.task_id, warg.name, warg.ptr, warg.length_byte, warg.time_ns, - // warg.threshold); - // // start watch variable - // start_watch_variable(warg); - // break; + case 0: + // copy watch_arg + if (copy_from_user(&warg, (watch_arg *)ioctl_param, sizeof(warg))) { + return -EACCES; + } + printk(KERN_INFO + "Watch_arg: task_id=%d, name=%s, ptr=%p, length_byte=%d, " + "time_ns=%ld, threshold=%lld\n", + warg.task_id, warg.name, warg.ptr, warg.length_byte, warg.time_ns, + warg.threshold); + // start watch variable + start_watch_variable(warg); + break; case 1: printk(KERN_INFO "variable_monitor 1\n"); ret = copy_from_user(&dump_param, (ioctl_dump_param *)ioctl_param, @@ -86,16 +86,16 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num, } printk(KERN_INFO "copy_to_user \n"); break; - case 0: - printk(KERN_INFO "variable_monitor test 2\n"); - ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid)); - diag_test(wpid.pid); - /* code */ - break; + // case 0: + // printk(KERN_INFO "variable_monitor test 2\n"); + // ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid)); + // diag_test(wpid.pid); + // /* code */ + // break; default: - printk(KERN_INFO "variable_monitor test default\n"); - ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid)); - diag_test(wpid.pid); + // printk(KERN_INFO "variable_monitor test default\n"); + // ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid)); + // diag_test(wpid.pid); break; } return 0; diff --git a/source/module/monitor_kernel_lib.c b/source/module/monitor_kernel_lib.c index 05515d4..47021f0 100644 --- a/source/module/monitor_kernel_lib.c +++ b/source/module/monitor_kernel_lib.c @@ -101,8 +101,61 @@ static void clear_all_watch(void) { memset(kernel_wtimer_list, 0, sizeof(kernel_wtimer_list)); } +static void sample_task_work(struct work_struct *work){ + kernel_watch_timer *k_watch_timer = container_of(work, kernel_watch_timer, wk); + + if (k_watch_timer->threshold_num <= 0) return; + + 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; + + vm_record.id = event_id; + vm_record.et_type = 0; //! todo event type + vm_record.tv = ktime_get_real(); + vm_record.threshold_num = k_watch_timer->threshold_num; + + for (int i = 0; i < vm_record.threshold_num; 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); + diag_variant_buffer_reserve(&load_monitor_variant_buffer, + sizeof(variable_monitor_record)); + 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); + + rcu_read_unlock(); + + do_each_thread(g, p) { + if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) || + p->__state == TASK_IDLE || 1) { + + get_task_struct(p); // count +1 + + tsk_info.et_type = 1; //! todo event type + tsk_info.id = event_id; + tsk_info.tv = vm_record.tv; + diag_tsk(p, &tsk_info); + + put_task_struct(p); // count -1 + + push_tsk_info(&tsk_info, &flags); // push to buffer + } + } + while_each_thread(g, p); +} /** - * @brief all module function init. orig_X | buffer + * @brief all module function init. orig_X | buffer | workqueue * * @return int */ @@ -115,6 +168,11 @@ int monitor_init(void) { ret = init_buffer(50 * 1024 * 1024); // 50M if (ret) return -1; + // init workqueue + for (int i=0; i < MAX_TIMER_NUM; i++) { + kernel_watch_timer *kw_timer = &kernel_wtimer_list[i]; + INIT_WORK(&kw_timer->wk, sample_task_work); + } return 0; } @@ -185,6 +243,7 @@ void clear_watch(pid_t pid) { start_all_hrTimer(); // restart timer } + /** * @brief main callback function * @@ -195,7 +254,6 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { kernel_watch_timer *k_watch_timer = container_of(timer, kernel_watch_timer, hr_timer); int i = 0, j = 0; - int buffer[TIMER_MAX_WATCH_NUM]; // Buffer to store the messages kernel_watch_arg *kwarg; // check all watched kernel_watch_arg @@ -203,66 +261,17 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { kwarg = &k_watch_timer->k_watch_args[i]; if (read_and_compare(kwarg->kptr, kwarg->length_byte, kwarg->greater_flag, kwarg->unsigned_flag, kwarg->threshold)) { - buffer[j] = i; + k_watch_timer->threshold_buffer[j] = i; j++; } } if (j > 0) // if any threshold reached { - 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}; - - vm_record.id = event_id; - vm_record.et_type = 0; //! todo event type - vm_record.tv = ktime_get_real(); - vm_record.threshold_num = j; - - // printk("-------------------------------------\n"); - // printk("-------------watch monitor-----------\n"); - // printk("Threshold reached:\n"); - for (i = 0; i < j; i++) { - kwarg = &k_watch_timer->k_watch_args[buffer[i]]; - k_w_arg2threshold(kwarg, &vm_record.threshold_record[i]); - } - rcu_read_lock(); - - diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags); - diag_variant_buffer_reserve(&load_monitor_variant_buffer, - sizeof(variable_monitor_record)); - 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); - - rcu_read_unlock(); - - do_each_thread(g, p) { - if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) || - p->__state == TASK_IDLE || 1) { - - get_task_struct(p); - - tsk_info.et_type = 1; //! todo event type - tsk_info.id = event_id; - tsk_info.tv = vm_record.tv; - - diag_tsk(p, &tsk_info); - - put_task_struct(p); - - push_tsk_info(&tsk_info, &flags); - } - } - while_each_thread(g, p); - - // print_task_stack(); + k_watch_timer->threshold_num = j; // restart timer after 5s hrtimer_forward(timer, timer->base->get_time(), ktime_set(5, 0)); //! todo - printk("-------------------------------------\n"); + // highpri_wq + queue_work(system_highpri_wq, &k_watch_timer->wk); } else { // keep frequency hrtimer_forward(timer, timer->base->get_time(), k_watch_timer->kt); diff --git a/source/module/monitor_timer.h b/source/module/monitor_timer.h index 5926142..3253ba9 100644 --- a/source/module/monitor_timer.h +++ b/source/module/monitor_timer.h @@ -1,4 +1,5 @@ #include +#include #define MAX_TIMER_NUM (128) // max timer number #define TIMER_MAX_WATCH_NUM (32) // A timer max watch number at once time @@ -33,6 +34,10 @@ typedef struct { unsigned sentinel; // sentinel kernel_watch_arg k_watch_args[TIMER_MAX_WATCH_NUM]; // all watched kernel_watch_arg + int threshold_num; // all over threshold number, + // 0 means no handle needed + int threshold_buffer[TIMER_MAX_WATCH_NUM]; // + struct work_struct wk; // for handle } kernel_watch_timer; // Global variable