summaryrefslogtreecommitdiff
path: root/source/module
diff options
context:
space:
mode:
authorzy <[email protected]>2023-11-23 18:12:57 +0800
committerzy <[email protected]>2023-11-23 18:12:57 +0800
commit1df11cd6e4534ac2c2759d29718743ef5ceb6f2b (patch)
tree9265db834b7c07934d9cb9c77cf70560aa612d1d /source/module
parent316174b71e7c192f0139b5c294c80b5f2292be51 (diff)
add workqueue
Diffstat (limited to 'source/module')
-rw-r--r--source/module/monitor_kernel.c46
-rw-r--r--source/module/monitor_kernel_lib.c119
-rw-r--r--source/module/monitor_timer.h5
3 files changed, 92 insertions, 78 deletions
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 <linux/hrtimer.h>
+#include <linux/workqueue.h>
#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